package com.falcon.generator.vben.impl;

import com.falcon.config.GeneratorConfig;
import com.falcon.domain.ftl.TsTypeModel;
import com.falcon.generator.vben.domain.ftl.ApiType;
import com.falcon.parser.ApiTypeParser;
import com.falcon.constants.FtlConstant;
import com.falcon.generator.vben.ITsTypeGenerator;
import com.falcon.utils.PathUtil;
import com.swan.core.utils.TxtFileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public class TsTypeGenerator extends AbsVbenGenerator implements ITsTypeGenerator {

    @Autowired
    private ApiTypeParser apiTypeParser;

    @Override
    public void generateCode(Class clz) {

        // 解析类型
        List<ApiType> apiTypes = this.apiTypeParser.parse(clz);

        apiTypes.forEach(this::createTsType);
    }

    @Override
    public void generateCode(TsTypeModel tsTypeModel) {
        // 根据模板生成代码
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("tsTypeModel", tsTypeModel);

        GeneratorConfig.VbenConfig vbenConfig = config.getVbenConfig();
        // 生成代码
        String code = freemarkerTemplateInside.getContent(FtlConstant.FTL_TS_TYPE, dataMap);

        // 处理包结构
        String filePath = PathUtil.getPath(config.getProjectPath(),
                vbenConfig.getRelativeBasePath() + vbenConfig.getApiModelPath(),
                "", tsTypeModel.getName(), ".ts");

        // 写入文件
        TxtFileUtil.writeFile(filePath, true, code);
    }

    private void createTsType(ApiType apiType) {
        // 获取依赖
        List<String> dependencies = this.getDependencies(apiType);

        List<TsTypeModel.TypeField> fields = apiType.getFields().stream()
                .map(field -> new TsTypeModel.TypeField(field.getName(), field.getType()))
                .collect(Collectors.toList());

        TsTypeModel tsTypeModel = new TsTypeModel();
        tsTypeModel.setName(apiType.getName());
        tsTypeModel.setParentName(apiType.getParentName());
        tsTypeModel.setDependencies(dependencies);
        tsTypeModel.setFields(fields);

       generateCode(tsTypeModel);
    }

    private List<String> getDependencies(ApiType apiType) {
        Set<String> dependencies = new HashSet<>();
        if (Objects.nonNull(apiType.getParentClass())) {
            dependencies.add(apiType.getParentName());
        }
        apiType.getFields().stream()
                .map(ApiType.ApiField::getDependTypes)
                .flatMap(Collection::stream)
                .filter(apiField -> !apiField.getSimpleName().equals(apiType.getName()))
                .forEach(item -> dependencies.add(item.getSimpleName()));

        List<String> dependencyList = new ArrayList<>(dependencies);
        Collections.sort(dependencyList);
        return dependencyList;
    }



}

